<script setup>
import { reactive, ref, toRaw } from "vue";
import { UploadFilled } from "@element-plus/icons-vue";

import Header from "@/components/header";
import PreviewImage from "@/components/previewImage";
import Titledivider from "@/components/titleDivider";

import useLoading from "@/hocks/useLoading";
import useImageType from "@/hocks/useImageType";
import useSendEvent from "@/hocks/useSendEvent";
import useMessageBox from "@/hocks/useMessage";
import useFileRender from "@/hocks/useReadFile";
import useDownload from "@/hocks/useDownload";

const fileList = reactive([]);
const handleFileList = reactive([]);
const sendEvent = useSendEvent();
const message = useMessageBox();
const readFileRender = useFileRender();
const downloadFile = useDownload();
const [_, requiredImageType] = useImageType();
const setLoading = useLoading({ lock: true, visible: false, text: "加载中" });

const formRef = ref();
const urlInputRef = ref();
const widthRef = ref();
const heightRef = ref();
const formModel = reactive({
  width: "",
  height: "",
  imageurl: "",
});
const formRules = reactive({
  width: [
    {
      required: true,
      message: "请输入需要转换的长度",
      trigger: "blur",
    },
    {
      validator(_, value, callback) {
        if (/^[1-9][0-9]*$/.test(value) && Number(value) >= 100) {
          return callback();
        }
        return callback(new Error("只能输入大于100的正整数"));
      },
      trigger: "change",
    },
  ],
  height: [
    {
      required: true,
      message: "请输入需要转换的宽度",
      trigger: "blur",
    },
    {
      validator(_, value, callback) {
        if (/^[1-9][0-9]*$/.test(value) && Number(value) >= 100) {
          return callback();
        }
        return callback(new Error("只能输入大于100的正整数"));
      },
      trigger: "change",
    },
  ],
});

const delImage = ({ info }, handled) => {
  try {
    setLoading({ visible: true, text: "图片删除中，请等待！" });
    const { filename, url } = info;
    const fileListDel = handled ? handleFileList : fileList;
    const delImageIndex = fileListDel.findIndex(
      (item) => item.filename === filename && item.url === url
    );
    fileListDel.splice(delImageIndex, 1);
    urlInputRef.value.focus();
  } catch (e) {
    console.error("del image is fail... in:", e);
    return message("error", "删除图片失败!" + e.message);
  }
  setLoading({ visible: false });
};

const existsFileList = (bufferResult, filename) => {
  const byteLength = bufferResult.byteLength;
  let exists = false;
  if (bufferResult && filename) {
    exists = fileList.find(
      (item) =>
        item.filename === filename && item.buffer.byteLength === byteLength
    );
  } else {
    exists = fileList.find(
      (item) => item.remote && item.remote === bufferResult
    );
  }
  if (exists !== undefined)
    throw new Error("文件列表中已经存在相同的图片了...");
};

const dragUpload = async (uploadFile) => {
  try {
    setLoading({ visible: true, text: "上传图片中，请等待！" });
    const { raw, name: filename } = uploadFile;
    requiredImageType(raw.type);

    const blobFile = new Blob([raw]);
    const url = URL.createObjectURL(blobFile);

    const bufferResult = await readFileRender(blobFile);
    existsFileList(bufferResult, filename);
    fileList.push({ filename, url, buffer: bufferResult });
    widthRef.value.focus();
  } catch (e) {
    console.error("drag upload is fail... in:", e);
    message("error", "上传图片失败！" + e.message);
  }
  setLoading({ visible: false });
};

const transformImage = (formInstance) => {
  return formInstance
    .validate()
    .then(async (status) => {
      if (!fileList.length || !status)
        return message("warning", "请先上传文图片文件或填写图片参数哦！");
      setLoading({ visible: true, text: "正在处理图片中，请等待！" });

      const file = await sendEvent("transform", {
        size: toRaw(formModel),
        fileList: toRaw(fileList),
      });
      const rejectStatus = file.filter((item) => {
        if (item.status === "fulfilled") {
          const url = new Blob([new Int8Array(item.value.buffer)]);
          handleFileList.push({
            url: URL.createObjectURL(url),
            filename: item.value.filename,
            buffer: item.value.buffer,
          });
          return item;
        }
      });

      if (!rejectStatus.length) {
        message("error", "图片全部转换失败，请刷新界面后重试!");
      } else {
        const isAllTransform = rejectStatus.length === file.length;
        message(
          (isAllTransform && "图片全部转换成功，可在转换列表中下载！") ||
            "图片部分转换成功, 可在转换列表中下载！"
        );
      }
      setLoading({ visible: false });
    })
    .catch((fields) => {
      const keys = Object.keys(fields)?.[0];
      if (keys === "width") widthRef.value.focus();
      else heightRef.value.focus();
    });
};

const cleanForm = (formInstance) => {
  formInstance?.resetFields();
  widthRef.value.focus();
};

const addImageUrl = async () => {
  try {
    if (!formModel.imageurl) return message("error", "网络图片地址不可为空！");
    setLoading({ visible: true, text: "正在解析中..." });
    existsFileList(formModel.imageurl);
    const result = await sendEvent("judgeRemoteUrl", formModel.imageurl);
    if (!result) throw new Error("网络地址无效，请更换链接后重试！");
    const blob = new Blob([new Int8Array(result.buffer)]);
    fileList.push({
      url: URL.createObjectURL(blob),
      remote: formModel.imageurl,
      buffer: result.buffer,
      filename: result.filename,
    });
    formModel.imageurl = "";
    setLoading({ visible: false });
    urlInputRef.value.focus();
  } catch (e) {
    message("error", e.message);
    setLoading({ visible: false });
  }
};

const downloadHandleList = async () => {
  try {
    setLoading({ visible: true, text: "图片正在压缩中，请等待..." });
    if (!handleFileList.length)
      throw new Error("已转换列表内暂无图片信息，请转换图片后重试！");

    const result = await sendEvent("exportAll", handleFileList);
    if (!result) throw new Error("导出失败，请重试！");

    const { buffer, filename } = result;
    const blob = new Blob([new Int8Array(buffer)]);
    const url = URL.createObjectURL(blob);
    downloadFile({ url, filename });
  } catch (e) {
    message("error", e.message);
  }
  setLoading({ visible: false });
};
</script>

<template>
  <Header></Header>
  <section class="layout">
    <section class="dragUplaodSpace">
      <el-upload
        drag
        class="uploader"
        :show-file-list="false"
        :auto-upload="false"
        :multiple="true"
        :on-change="dragUpload"
      >
        <el-icon class="el-icon--upload"><upload-filled /></el-icon>
        <section class="el-upload__text">
          请将您需要处理的本地图片放置此处，<em>可拖拽或点击上传</em>
        </section>
      </el-upload>
      <section class="operateBtnSpace">
        <el-form
          ref="formRef"
          label-position="left"
          :model="formModel"
          :rules="formRules"
        >
          <el-row>
            <el-col :span="20">
              <el-form-item
                label-width="72px"
                prop="imageurl"
                label="网络资源:"
              >
                <el-input
                  ref="urlInputRef"
                  v-model="formModel.imageurl"
                  clearable
                  placeholder="请输入网络图片地址"
                /> </el-form-item
            ></el-col>
            <el-col :span="3" :offset="1">
              <el-button style="width: 100%" @click="addImageUrl" type="primary"
                >添加</el-button
              >
            </el-col>
          </el-row>
          <el-row class="sizeParameter">
            <el-col :span="11">
              <el-form-item label-width="72px" prop="width" label="长度:">
                <el-input
                  ref="widthRef"
                  placeholder="处理后图片的宽度"
                  v-model="formModel.width"
                  clearable
                />
              </el-form-item>
            </el-col>
            <el-col :offset="2" :span="11">
              <el-form-item label-width="72px" prop="height" label="宽度:">
                <el-input
                  ref="heightRef"
                  placeholder="处理后图片的高度"
                  v-model="formModel.height"
                  clearable
                />
              </el-form-item>
            </el-col>
          </el-row>
          <el-form-item>
            <el-button
              @click="transformImage(formRef)"
              type="primary"
              class="operateBtn"
              >转 换</el-button
            >
          </el-form-item>
        </el-form>
        <el-button
          @click="downloadHandleList()"
          type="success"
          class="operateBtn"
          >全部导出(已转换列表)</el-button
        >
        <el-button @click="cleanForm(formRef)" type="success" class="operateBtn"
          >清 空</el-button
        >
      </section>
    </section>
    <section class="imageSPace">
      <section class="uploadFileList">
        <Titledivider title="需要处理的图片" />
        <PreviewImage
          :data="fileList"
          @del-image="delImage"
          @downloadImage="downloadFile"
          noDataDes="暂无上传的图片资源，请上传！"
        />
      </section>
      <section class="handleFileList">
        <Titledivider title="转换完成图片" />
        <PreviewImage
          type="transform"
          :data="handleFileList"
          @del-image="(...rest) => delImage(...rest, true)"
          @downloadImage="downloadFile"
          noDataDes="请上传后图片资源后进行转换！"
        />
      </section>
    </section>
  </section>
</template>

<style scoped lang="less">
@import url("./index.less");
</style>
